#define PUDGE_META_TUPLE_SPEC BOOST_PP_ITERATION()

template<BOOST_PP_ENUM_PARAMS(PUDGE_META_TUPLE_SPEC,class T)>
struct dunion<BOOST_PP_ENUM_PARAMS(PUDGE_META_TUPLE_SPEC,T)>
{
	typedef dunion<BOOST_PP_ENUM_PARAMS(PUDGE_META_TUPLE_SPEC,T)> self_type;
	enum
	{
#define PUDGE_META_DUNION_M(Z,N,A) T ## N ## _TYPE
		BOOST_PP_ENUM(PUDGE_META_TUPLE_SPEC,PUDGE_META_DUNION_M,)
#undef PUDGE_META_DUNION_M
		, NULL_TYPE
	} type;
	union
	{
#define PUDGE_META_DUNION_M(Z,N,A) T ## N t ## N;
		BOOST_PP_REPEAT(PUDGE_META_TUPLE_SPEC,PUDGE_META_DUNION_M,)
#undef PUDGE_META_DUNION_M
	};
	template<class F> void operator()(F & f)
	{
		switch(type)
		{
#define PUDGE_META_DUNION_M(Z,N,A) case T ## N ## _TYPE: f(t ## N); break;
			BOOST_PP_REPEAT(PUDGE_META_TUPLE_SPEC,PUDGE_META_DUNION_M,)
#undef PUDGE_META_DUNION_M

case NULL_TYPE:
	throw -1;
	break;
		};
	}
#define PUDGE_META_DUNION_M(Z,N,A) \
	self_type & operator = (T ## N t ## N ##_) \
	{ \
	t ## N = t ## N ## _; \
	type = T ## N ## _TYPE; \
	return *this; \
	}
	BOOST_PP_REPEAT(PUDGE_META_TUPLE_SPEC,PUDGE_META_DUNION_M,)
#undef PUDGE_META_DUNION_M
};